React is a popular library for creating web apps and mobile apps.
In this article, we’ll look at some tips for writing better React apps.
setState on Parent Inside Child Component
We can pass a function from the parent to the child component.
Then we can call it inside the child to set the state if the parent.
For instance, we can write:
import React, { useState, useEffect, useCallback, useRef } from "react";
function Parent() {
const [parentState, setParentState] = useState(0);
const wrapperSetParentState = useCallback(val => {
setParentState(val);
}, [setParentState]);
return (
<div>
<Child
setParentState={wrapperSetParentState}
/>
<div>{parentState}</div>
</div>
);
};
function Child({ setParentState }) {
const [childState, setChildState] = useState(0);
useEffect(() => {
setParentState(childState);
}, [setParentState, childState]);
const onSliderChange = e => {
setChildState(e.target.value);
};
return (
<div>
<input
type="range"
min="1"
max="100"
value={childState}
onChange={onSliderChange}
></input>
</div>
);
};
We created the Child
component with a slider input that takes a range of values.
Also, we defined the onSliderChange
function into the onChange
prop to watch for changes.
We set the e.target.value
, which has the slider’s value as the value of the childState.
We also watch the changes for the childState
to watch for changes for it.
And we called setParentState
to call the function from the Parent
that we passed into the props.
It set’s the parentState
value from the parent,
We then display the latest value of the parentState
in Parent
.
useCallback
lets us cache the value of parentState
if it hasn’t changed.
React Router v4 <NavLink> vs <Link>
NavLink
adds an active class to the link when it’s navigated to so that we can style it differently from the other links.
It takes an activeClassName
prop to let us change the class name.
For instance, we can write:
<NavLink to="/" activeClassName="active">profile</NavLink>
We can make the dynamic to style the link the way we want.
React Render String with Non-Breaking Spaces
We can style the white-space: nowrap
style to display strings with non-breaking spaces.
For instance, we can write:
<div style="white-space: nowrap">no breaks</div>
or
<div style={{ whiteSpace: 'nowrap' }}>no breaks</div>
React Async Rendering of Components
We can render async data by providing a loading message that’s displayed when something is loading.
If there’s data, then we display that instead of the loading message.
For instance, we can write:
import React from 'react';
class App extends React.PureComponent {
constructor(props){
super(props);
this.state = {
data: null
}
}
componentDidMount(){
fetch('https://randomuser.me/api')
.then((resp) => resp.json())
.then((response) => {
const [data] = response.results;
setState({ data });
});
}
render(){
return (<div>
{this.state.data === null ?
<div>Loading</div>:
<div>{this.state.data.name.first}</div>
}
</div>);
}
}
We display a loading message when the data
state is null
.
Otherwise, we show the data that we want to display from the API.
We fetch the data in componentDidMount
, which means that the data will be fetched when the component mounts.
Dispatch Action on App Load with React-Redux
We can call mapStateToProps
to map the states from the Redux stores as props of a component.
mapDispatchToProps
match the action dispatch functions to props of a component.
For instance, we can write:
class App extends Component {
componentDidMount() {
this.props.getUser()
}
render() {
return this.props.isReady
? <div> ready </div>
: <div>not ready</div>
}
}
const mapStateToProps = (state) => ({
isReady: state.isReady,
})
const mapDispatchToProps = dispatch => {
return {
getUser: () => dispatch(getUserActionCreator())
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
We create a mapStateToProps
function that takes a state
parameter, which has the state parameter with the Redux state.
Then we can get the isReady
state from it and map it to the isReady
prop in the key.
getUser
is mapped to a function that calls dispatch
to dispatch an action.
getUseractionCreator
returns an object that has the type
and payload
properties to pass those to the reducer and run the right action.
With function components, we can write:
import { appInit } from '../store/actions';
import { useDispatch } from 'react-redux';
const appInit = () => ({ type: APP_INIT });
export default App() {
const dispatch = useDispatch();
useEffect(() => dispatch(appInit()), [ dispatch ]);
return (<div>something</div>);
}
We call the useDispatch
hook to let us dispatch actions returned from the appInit
function, which also has the type
and payload
properties.
Conclusion
We can dispatch actions with React-Redux to manipulate the store.
Also, we can call parent component’s functions in a child component.
Different things can be rendered our way when we load data.